package org.delphy.indy2.containers
{
	import com.degrafa.paint.GradientStop;
	import com.degrafa.paint.LinearGradientStroke;
	
	import flash.filters.GlowFilter;
	
	import mx.containers.Canvas;
	import mx.core.UIComponent;
	import mx.effects.WipeDown;
	import mx.effects.WipeUp;

	public class CarbonFunTree extends Canvas
	{
		import com.degrafa.GeometryGroup;
		import com.degrafa.Surface;
		import mx.containers.Canvas;
		import mx.managers.PopUpManager;
		import mx.events.EffectEvent;
		import mx.events.FlexMouseEvent;
		
		import flash.display.DisplayObject;
		import flash.geom.Point;
		import flash.events.MouseEvent;
		import flash.events.Event;
		
		import com.degrafa.geometry.splines.BezierSpline;
		
		import caurina.transitions.Tweener;
		
		public var maxBranchSpreadX:Number=70;
		public var maxBranchSpreadY:Number=5;
		
		public var minBranchSteps:Number=3;
		public var maxBranchSteps:Number=6;
		
		public var maxKnotSpreadX:Number=10;
		
		public static const UP_DIRECTION:String="up";
		public static const DOWN_DIRECTION:String="down";
		
		public var direction:String="up";
		
		[Bindable]
		public var transitionTime:Number=1.2;
		
		private var _host:DisplayObject=null;
		
		private var widgetPositionArray:Array;

		public function get host():DisplayObject
		{ 
			return _host; 
		}

		public function set host(value:DisplayObject):void
		{
			if (value !== _host)
			{
				_host = value;
			}
		}
		
		private var surface:Surface;
		private var gr:GeometryGroup;
		private var trunkStroke:LinearGradientStroke;
		
		private var wipeDown:WipeDown;
		private var wipeUp:WipeUp;

		public function CarbonFunTree()
		{
			super();
			
			surface=new Surface();
			gr=new GeometryGroup();
			
			surface.addChild(gr);
			rawChildren.addChild(surface);
			
			trunkStroke=new LinearGradientStroke();
			trunkStroke.weight=1.3;
//			trunkStroke.gradientStops.push(new GradientStop(0xffffff,1));
//			trunkStroke.gradientStops.push(new GradientStop(0xffffff,0.7));
			trunkStroke.gradientStops.push(new GradientStop(0x0f2b0d,1));
			trunkStroke.gradientStops.push(new GradientStop(0x9ed8b0,0.7));
			
			
			wipeDown=new WipeDown();
			wipeDown.duration=transitionTime*1000;
			
			wipeUp=new WipeUp();
			wipeUp.duration=transitionTime*1000;
			
			horizontalScrollPolicy="off";
			verticalScrollPolicy="off";
			
			var glowFilter:GlowFilter=new GlowFilter();
			glowFilter.blurX=7;
			glowFilter.blurY=7;
			glowFilter.alpha=0.7;
			glowFilter.color=0x448ccb;
			
//			surface.filters=[glowFilter];			
		}
		
		private function generateTree(aWidth:Number,aHeight:Number):void{	
			widgetPositionArray=new Array();
					
			var startX:Number=aWidth/2;
			var startY:Number=aHeight;
			
			var lastY:Number=startY;
			
			var stepY:Number=aHeight/numChildren;
			
			var spline:BezierSpline=new BezierSpline(new Array());			
			spline.stroke=trunkStroke;			
			
			spline.addControlPoint(startX,startY);
			
			for(var i:uint=0;i<numChildren+1;i++){
				var growY:Number=stepY;
				
				var knotX:Number=startX + maxKnotSpreadX*randRange(-1,1);
				var knotY:Number;
				if(direction==UP_DIRECTION)
					knotY=lastY - growY;
				else if(direction==DOWN_DIRECTION)
					knotY=lastY + growY;
				
				lastY=knotY;
				
				spline.addControlPoint(knotX,knotY);
				
				var branchDirection:Number= i%2==0? 1: -1;
				
				if(i!=numChildren)
					generateBranch(knotX,knotY,branchDirection);
				else
					generateBranch(knotX,knotY,branchDirection,false);
			}

			gr.geometryCollection.addItem(spline);
			
		}
		
		private function generateBranch(startX:Number,startY:Number,branchDirection:Number,drawable:Boolean=true):void{
			var branchSteps:Number=Math.floor(randRange(minBranchSteps,maxBranchSteps));
			var lastX:Number=startX;
			var lastY:Number=startY;
			
			var widgetX:Number;
			var widgetY:Number;
			
			var branch:BezierSpline=new BezierSpline(new Array());
			branch.stroke=trunkStroke;
			branch.addControlPoint(startX,startY);
			
			for(var i:uint=1;i<=branchSteps;i++){
				var branchSpreadX:Number=maxBranchSpreadX/branchSteps * Math.random();
				var branchSpreadY:Number=maxBranchSpreadY * randRange(1,1);
				
				var knotX:Number= branchDirection>0? lastX+branchSpreadX : lastX-branchSpreadX;
				var knotY:Number=lastY+branchSpreadY;	
				
				lastX=knotX;
				lastY=knotY;
				
				if(i==branchSteps-1){
					widgetX=lastX;
					widgetY=lastY;
				}
				
				if(drawable)
					branch.addControlPoint(knotX,knotY);
			}
			
			widgetPositionArray.push({x:widgetX,y:widgetY,branchDirection:branchDirection});
			
			gr.geometryCollection.addItem(branch);
			
		}
		
		public function popUp():void{
			if(_host==null)
				_host=parent;
						
			var hostCenter:Point=new Point(_host.x,_host.y);
			hostCenter=_host.parent.localToGlobal(hostCenter);
			
			x=hostCenter.x+ (_host.width-this.width)/2;
			y=hostCenter.y-this.height;
			
			generateTree(width,height);
			
			PopUpManager.addPopUp(this,_host,false);
			
			for(var i:uint=0;i<widgetPositionArray.length-1;i++){
				var child:UIComponent=getChildAt(i) as UIComponent;
				
				var pt:Object=widgetPositionArray[i];
				
				if(pt.branchDirection>0)
					child.x=pt.x;
				else
					child.x=pt.x-child.measuredWidth;
				child.y=pt.y-child.measuredHeight/2;
			}
			
			if(direction==UP_DIRECTION)
				wipeUp.play([this]);
			else if(direction==DOWN_DIRECTION)
				wipeDown.play([this]);
				
//			addEventListener(MouseEvent.CLICK,close);
			addEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE,close);	
		}
		
		public function close(evt:Event=null):void{
			PopUpManager.removePopUp(this);

//			removeEventListener(MouseEvent.CLICK,close);
			removeEventListener(FlexMouseEvent.MOUSE_DOWN_OUTSIDE,close);	
			
			widgetPositionArray=[];
		}
		
		private function randRange(min:Number, max:Number):Number {
			var randomNum:Number = Math.floor(Math.random() * (max - min + 1)) + min;
			return randomNum;
		}
		
		private function randDigit():Number{
			var randomNum:Number=randRange(-1,1);
			
			return randomNum>0?1:-1;
		}
		
	}
}